from typing import List,Union
import sys,os
#sys.path.append("C:\\Users\\Administrator\\Desktop\\VSCode\\IMS")
    
from fastapi import APIRouter,Depends,UploadFile,File
from fastapi.responses import FileResponse
# from fastapi.logger import logger

from tortoise import connections
from tortoise.transactions import atomic,in_transaction
from tortoise.expressions import Q
from tortoise.functions import Sum,Count
from tortoise.query_utils import Prefetch
from tortoise.contrib.pydantic import pydantic_queryset_creator

from models import Project,User,ProjectMembers,ProjectFiles,ProjectGroups,ProjectAuditRules,ProjectAuditRecords,ProjectBatches,ProjectLog
from scheams import (Project_Pydantic,ProjectIn_Pydantic
                     ,Response200,Response400
                     ,ProjectMembers_Pydantic,ProjectInWithId_Pydantic
                     ,ProjectMembersWithId_Pydantic
                     ,ProjectFiles_Pydantic,ProjectGroups_Pydantic
                     ,User_Pydantic,ProjectAuditRulesIn_Pydantic
                     ,ProjectAuditRules_Pydantic,ProjectAuditRecords_Pydantic
                     ,ProjectAuditRecordsIn_Pydantic,ProjectAuditRecordsAll_Pydantic)
from core import deps,config,get_logger
from utils import getAuditRulesTotalPont,writeExcel

logger = get_logger(__name__)

# project_audit = APIRouter(tags=["项目评审相关"],dependencies=[Depends(deps.get_current_user)])
project_audit = APIRouter(tags=["项目评审相关"],dependencies=[Depends(deps.get_current_user)])
@project_audit.get("/getUserGroups",summary="获取用户所在的评审组")
async def getUserGroups(user:User = Depends(deps.get_current_user)):
    
    return Response200(data=[ k[0] for k in await ProjectGroups.filter(group_member_id=user.username).values_list("group_name") ])

@project_audit.post("/getProjectsByGroup",summary="获取待评审项目列表")
async def getProjectsByGroup(batch_name: str
                             ,limit: int = 10
                             ,page: int = 1
                             ,status: List[config.settings.ProjectStatus] = [config.settings.ProjectStatus.PROFESSIONAL_AUDIT.value]
                             ,user:User = Depends(deps.get_current_user)):
    skip = (page - 1)*limit
    # 分页 page：页码 limit: 每页记录数量
    
    groups = [ k[0] for k in await ProjectGroups.filter(group_member_id=user.username).values_list("group_name") ]
    
    logger.debug("------{}".format(groups))
    # status = [config.settings.ProjectStatus.SUBMITTED.value,config.settings.ProjectStatus.PROFESSIONAL_AUDIT.value]
    
    # 已评审列表
    audited = [ k[0] for k in await ProjectAuditRecords.filter(user_id=user.username).values_list("project_id") ]
    
    baseQuery = Project.filter(statu__in=status
                       ,project_group__in = groups
                       ,id__not_in=audited
                       ,project_batch_id=batch_name)
    
    cnt = await baseQuery.count()
    
    records = await Project_Pydantic.from_queryset(baseQuery.offset(skip).limit(limit))
    
    return Response200(data={'cnt': cnt
                             ,'records': records})

@project_audit.put("/auditRule",summary="增加评审规则")
async def addAuditRule(projectAuditRuleForm: ProjectAuditRulesIn_Pydantic):
    
    # 判断该打分项是否存在
    rule = await ProjectAuditRules.filter(group_name=projectAuditRuleForm.group_name,dimension=projectAuditRuleForm.dimension)
    if rule :
        return Response400(msg="该维度已存在")
    
    if projectAuditRuleForm.max_point > 100 or projectAuditRuleForm.max_point < 1:
        return Response400(msg="维度分值不能大于100或小于1")
    
    max = await getAuditRulesTotalPont(projectAuditRuleForm.group_name)
    logger.debug("------{}".format(max))
    if projectAuditRuleForm.max_point > 100 - max:
        return Response400(msg="评审规则总分已大于100")
    
    rule_name = "-".join([projectAuditRuleForm.group_name,"评审规则"])
    
    saved_rule = await ProjectAuditRules.create(**projectAuditRuleForm.dict(),rule_name=rule_name)
    return Response200(data=await ProjectAuditRules_Pydantic.from_tortoise_orm(saved_rule))

@project_audit.delete("/auditRule",summary="删除评审规则")
async def deleteAuditRule(projectAuditRuleForm: ProjectAuditRules_Pydantic):
    await ProjectAuditRules.filter(id=projectAuditRuleForm.id).delete()
    return Response200(msg="删除成功")

@project_audit.post("/auditRule",summary="修改评审规则")
async def modifyAuditRule(projectAuditRuleForm: ProjectAuditRules_Pydantic):
    
    if projectAuditRuleForm.max_point > 100 or projectAuditRuleForm.max_point < 1:
        return Response400(msg="维度分值不能大于100或小于1")
    
    rule = await ProjectAuditRules.get(id=projectAuditRuleForm.id)
    
    max = await getAuditRulesTotalPont(projectAuditRuleForm.group_name)
    logger.debug("------{}".format(max))
    if projectAuditRuleForm.max_point > 100 - (max - rule.max_point):
        return Response400(msg="评审规则总分已大于100")
    
    
    # 如果维度名称变更 检测名称是否重复
    if rule.dimension != projectAuditRuleForm.dimension:
        rule_temp = await ProjectAuditRules.filter(group_name=projectAuditRuleForm.group_name,dimension=projectAuditRuleForm.dimension)
        if rule_temp :
            return Response400(msg="该维度已存在")
    
    dict = projectAuditRuleForm.model_dump()
    dict.pop("id")
    await rule.update_from_dict(dict).save()
    
    return Response200(msg="修改成功")

@project_audit.get("/auditRule",summary="获取评审规则")
async def getAuditRules(group_name: config.settings.ProjectGroupName):
    
    res = ProjectAuditRules.filter(group_name=group_name)
    
    return Response200(data=await ProjectAuditRules_Pydantic.from_queryset(res))


@project_audit.post("/audit",summary="评分")
async def audit(auditRecordsForms: List[ProjectAuditRecordsIn_Pydantic]
                ,project_id: int
                ,user:User = Depends(deps.get_current_user)):
    
    if auditRecordsForms is None or auditRecordsForms.__len__() == 0:
        return Response400(msg="不可提交空记录")
    
    # 判重
    records = await ProjectAuditRecords.filter(project_id=project_id,user_id=user.username)
    if records:
        return Response400(msg="该项目您已评过分，不可重复评分")
    
    rules = await ProjectAuditRules.filter(group_name=auditRecordsForms[0].group_name)
    
    # 将输入记录 列表 -> 字典
    recordsMap = {}
    for item in auditRecordsForms:
        recordsMap.update({item.dimension : item})
        
    logger.debug("========{}".format(recordsMap))
    
    records = []
    for rule in rules:
        
        record = recordsMap.get(rule.dimension)
        
        # 判断是否缺少维度
        if record is None:
            return Response400(msg="缺少维度：[{}]".format(rule.dimension))

        # 判断所打分值是否合规
        if record.point < 0 or record.point > rule.max_point:
            return Response400(msg="维度：[{}]分值不合规".format(rule.dimension))
        
        records.append(ProjectAuditRecords(**record.dict(),project_id=project_id,user_id=user.username))
    
    # 检测评分项
    
    await ProjectAuditRecords.bulk_create(
        records
    )
    
    project = await Project.get(id=project_id)
    
    # 更新项目状态
    if project.statu == config.settings.ProjectStatus.SUBMITTED.value:
        project.statu = config.settings.ProjectStatus.PROFESSIONAL_AUDIT.value
        await project.save()
    if project.statu == config.settings.ProjectStatus.ROFESSIONAL_AUDIT_SUCCESS.value:
        project.statu = config.settings.ProjectStatus.INNOVATION_BOARD_AUDIT.value
        await project.save()
    
    return Response200()

@project_audit.get("/getAuditRecords",summary="获取当前评审者的评分记录")
async def getAuditRecords(project_id: Union[int,None] = None
                          ,limit: int = 10
                          ,page: int = 1
                          ,user:User = Depends(deps.get_current_user)):
    
    skip = (page - 1)*limit
    res = None
    if project_id:
        res = ProjectAuditRecords.filter(project_id=project_id,user_id=user.username)
        
    else:
        res = ProjectAuditRecords.filter(user_id=user.username)
    # .values("group_name","point","createTime","id","updateTime","dimension",project="project__project_name",user_name="user_id")
    logger.debug("=======.{}".format(res))
    resList = await ProjectAuditRecords_Pydantic.from_queryset(res.offset(skip).limit(limit))
    
    # final = [ k.model_dump_json() for k in resList]
    
    return Response200(data=resList)

@project_audit.get("/getAuditedProject",summary="获取已评分项目")
async def getAuditedProject(batch_name: str
                            ,limit: int = 10
                            ,page: int = 1
                            ,user:User = Depends(deps.get_current_user)):
    
    skip = (page - 1)*limit
    
    res = [ k[0] for k in await ProjectAuditRecords.filter(user_id=user.username).values_list("project_id") ]
    
    basequery = Project.filter(id__in=res,project_batch_id=batch_name)
    
    cnt = await basequery.count()
    records = await Project_Pydantic.from_queryset(
        basequery.prefetch_related(
            Prefetch("audit_records", queryset=ProjectAuditRecords.filter(user_id=user.username))).offset(skip).limit(limit))
    
    return Response200(data={"cnt": cnt,
                             "records": records})


@project_audit.get("/getProjectAllRecords",summary="获取该项目所有评分记录")
async def getProjectAllRecords(project_id: int
                               ,group_name: config.settings.ProjectGroupName
                               ,limit: int = 10
                               ,page: int = 1):
    
    skip = (page - 1)*limit
    
    res = ProjectAuditRecords.filter(project_id=project_id,group_name=group_name).offset(skip).limit(limit)
    
    return Response200(data=await ProjectAuditRecords_Pydantic.from_queryset(res))


def getDataDict(projects: Project_Pydantic,group_name,group_members,rules):
    
    res = []
    
    
    
    group_members_normal = list(filter(lambda x: x.group_member_role != config.settings.ProjectGroupMemberRole.LEADER.value,group_members))
    grou_member_leader = list(filter(lambda x: x.group_member_role == config.settings.ProjectGroupMemberRole.LEADER.value,group_members))[0]
    
    leaderPointFlag = True if len(list(
        filter(lambda x: len(
            list(filter( lambda y: y.user.username == grou_member_leader.group_member.username 
                        ,x.audit_records))
            )>0
               , list(filter(lambda z:z.audit_records and len(z.audit_records)>0,projects)))
        )) > 0 else False
    
    logger.debug("-------是否组长参与打分标识为{}".format(leaderPointFlag))
    
    i = 1 # 记录序号
    for item in projects:
        project = {}
        project["序号"] = i
        i += 1
        project["项目编码"] = item.project_code
        project["专家组"] = item.project_group
        project["项目名称"] = item.project_name
        project["项目简介"] = item.project_brief
        
        dep_set = set()
        for member in item.project_member:
            dep_set.add(member.user_department)
        
        project["申报单位"] = ",".join(dep_set)
        project["团队项目/个人项目"] = item.project_class 
        project["项目联系人"] = item.project_owner.username
        project["联系电话"] = item.project_owner.phone
        
        
        points = {}
        if len(item.audit_records) > 0:
            for record in item.audit_records:
                logger.debug("=======record.user.username[{}]".format(record.user.username))
                logger.debug("=======points{}".format(points))
                if not points.__contains__(record.user.username):
                    points[record.user.username] = {record.dimension: record.point}
                else :
                    # logger.debug("==============points.get(record.user.username){}".format(points.get(record.user.username)))
                    dict = points.get(record.user.username)
                    logger.debug("==============list[{}]".format(list))
                    dict.update({record.dimension: record.point})
                    points[record.user.username] = dict
            
        logger.debug(points)
        
        j = 1 # 评委序号
        all_total = 0
        for k in group_members_normal:
            total = 0
            
            
            dict = points.get(k.group_member.username)
            logger.debug("==============dict[{}]".format(dict))
            if dict:
                for v in dict.keys():
                    logger.debug("==============v[{}]".format(v))
                    
                    project["评委"+str(j)+":"+v] = dict.get(v)
                    total += dict.get(v)
                project["评委"+str(j)+": 总分"] = total
            else:
                for v in rules:
                    project["评委"+str(j)+":"+v.dimension] = ""
                project["评委"+str(j)+": 总分"] = ""
            
            j += 1
            all_total += total
            
        # 组长评分
        if leaderPointFlag:
            leaderDict = points.get(grou_member_leader.group_member.username)
            leaderTotal = 0
            if leaderDict:
                for v in leaderDict.keys():
                        logger.debug("==============v[{}]".format(v))
                        
                        project["评委"+str(j)+":"+v] = leaderDict.get(v)
                        leaderTotal += leaderDict.get(v)
                project["评委"+str(j)+": 总分"] = leaderTotal
            else:
                for v in rules:
                    project["评委"+str(j)+":"+v.dimension] = ""
                project["评委"+str(j)+": 总分"] = ""
            all_total += leaderTotal
        
        project["专家组评审项目得分"] = "" if len(points.keys())==0 else all_total / len(points.keys())
        
        project_result = None
        log_list = list(filter(lambda log: log.project_group == group_name,item.project_log))
        log_list.sort(key=lambda x: x.id,reverse=True)
        final_log = log_list[0]
        if ( final_log.statu == config.settings.ProjectStatus.INNOVATION_BOARD_AUDIT_SUCCESS.value 
            or final_log.statu == config.settings.ProjectStatus.ROFESSIONAL_AUDIT_SUCCESS.value):
            project_result = "是"
        elif ( final_log.statu == config.settings.ProjectStatus.INNOVATION_BOARD_AUDIT_FAILED.value 
            or final_log.statu == config.settings.ProjectStatus.PROFESSIONAL_AUDIT_FAILED.value):
            project_result = "否"
        else:
            project_result = "未评审"
        project["是否通过"] = project_result
        
        res.append(project)
    return res

@project_audit.get("/getBatchProjectsWithAuditInfo",summary="获取批次项目及打分评审结果")
async def getAuditedProjects(group_name: config.settings.ProjectGroupName
                             ,batch_name: str
                             ,isFile: bool = False
                             ,limit: int = 10
                             ,page: int = 1
                             ,user:User = Depends(deps.get_current_user)):
    
    skip = (page - 1)*limit
    
    projectGroup = await ProjectGroups.filter(group_name=group_name,group_member_id=user.username).first()
    
    if not projectGroup or projectGroup.group_member_role != config.settings.ProjectGroupMemberRole.LEADER:
        return Response400(msg="用户非评审组组长，无此查询权限")
    
    # 非组长组成员
    group_members = await ProjectGroups_Pydantic.from_queryset(ProjectGroups.filter(group_name=group_name))
    # group_members_names = [ item[0] for item in group_members]
    # logger.debug("该评审组成员有[{}]".format(group_members_names))
    
    # 项目规则
    rules = await ProjectAuditRules_Pydantic.from_queryset(ProjectAuditRules.filter(group_name=group_name))
    
    # logger.debug("该评审组共有[{}]名非组长成员，共有[{}]个评分维度".format(len(group_members),len(rules)))
    
    # records = await ProjectAuditRecords.annotate(cnt=Count("id")).filter(
    #     group_name=group_name
    #     ,cnt__gte=(len(group_members)*len(rules))
    #     ,user_id__in=group_members_names).group_by("project_id").values_list("project_id")
    
    # project_ids = [ k[0] for k in records]
    
    baseQuery = Project.filter(project_batch_id=batch_name).prefetch_related(
            Prefetch("audit_records", queryset=ProjectAuditRecords.filter(group_name=group_name)))
    
    if isFile:
        res = await Project_Pydantic.from_queryset(baseQuery)
    
        resList = getDataDict(res,group_name,group_members,rules)
        xlsx_full,xlsx = writeExcel(config.settings.TEMP_FILE_PATH,"{}评审结果".format(batch_name),resList)
        return FileResponse(xlsx_full,filename=xlsx)
    else:
        cnt = await baseQuery.count()
        res = await Project_Pydantic.from_queryset(baseQuery.offset(skip).limit(limit))
        resList = getDataDict(res,group_name,group_members,rules)
    
        return Response200(data={"cnt":cnt
                                 ,"records":resList})
    
@project_audit.post("/updateProjectStatu",summary="更新项目状态")
async def updateProjectStatu(project_id: int
                             ,statu: config.settings.ProjectStatus
                             ,user:User = Depends(deps.get_current_user)):
    
    
    async with in_transaction():
        project = await Project.get(id=id)
        
        pre_statu = project.statu
        
        project.statu = statu
        await project.save()
        
        await ProjectLog.create(project=project,pre_statu=pre_statu,statu=project.statu,user=user)
        
    return Response200()

@project_audit.get("/getProjectByProjectCode",summary="根据项目编码获取项目")
async def getProjectByProjectCode(project_code: str,user:User = Depends(deps.get_current_user)):
    
    baseQuery = Project.get(project_code=project_code)
    project = await  baseQuery
    
    groupInfo = await ProjectGroups.filter(group_member_id=user.username,group_name=project.project_group).first()
    
    if not groupInfo:
        return Response400(msg="无权限！")
    
    if groupInfo.group_member_role == config.settings.ProjectGroupMemberRole.LEADER.value:
        baseQuery = baseQuery.prefetch_related(
            Prefetch("audit_records",queryset=ProjectAuditRecords.filter(group_name=groupInfo.group_name))
        )
    else:
        baseQuery = baseQuery.prefetch_related(
            Prefetch("audit_records",queryset=ProjectAuditRecords.filter(user_id=groupInfo.group_member_id))
        )
    
    return Response200(data=await Project_Pydantic.from_queryset_single(baseQuery))

@project_audit.post("/submitProjectAuditRes",summary="提交项目评审结果")
async def getProjectByProjectCode(project_id: int
                                  ,project_group: config.settings.ProjectGroupName
                                  ,isPassed: bool
                                  ,project_type: Union[config.settings.ProjectType,None] = None
                                  ,user:User = Depends(deps.get_current_user)):
    
    # 非组长无权限
    projectGroup = await ProjectGroups.filter(group_name=project_group,group_member_id=user.username).first()
    if not projectGroup or projectGroup.group_member_role != config.settings.ProjectGroupMemberRole.LEADER:
        return Response400(msg="用户非评审组组长，无此查询权限")
    
    baseQuery = Project.get(id=project_id)
    project = await  baseQuery
    
    ## 检查评审组是否已全部评审完成
    groupMembers = await ProjectGroups_Pydantic.from_queryset(ProjectGroups.filter(group_name=project.project_group))
    
    for member in groupMembers:
        if member.group_member_role != config.settings.ProjectGroupMemberRole.LEADER.value and not await ProjectAuditRecords.filter(project_id=project_id,group_name=project_group,user_id=member.group_member.username).exists():
            return Response400(msg="组员[{}]还未打分，无法提交".format(member.group_member.fullname))
    
    async with in_transaction():
        
        pre_statu = project.statu
        
        if project.statu == config.settings.ProjectStatus.PROFESSIONAL_AUDIT.value:
            project.statu = config.settings.ProjectStatus.ROFESSIONAL_AUDIT_SUCCESS.value if isPassed else config.settings.ProjectStatus.PROFESSIONAL_AUDIT_FAILED.value
        elif project.statu == config.settings.ProjectStatus.INNOVATION_BOARD_AUDIT.value :
            project.project_type = project_type
            project.statu = config.settings.ProjectStatus.INNOVATION_BOARD_AUDIT_SUCCESS.value if isPassed else config.settings.ProjectStatus.INNOVATION_BOARD_AUDIT_FAILED.value
        else:
            Response400(msg="项目状态异常")
        await project.save()
        await ProjectLog.create(project=project,pre_statu=pre_statu,statu=project.statu,user=user,project_group=project_group)
    
    return Response200(msg="提交成功")